﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Xml;

namespace WebUI.Controllers
{
    public class ExportController : Controller
    {
        //
        // GET: /Export/

        private StringBuilder content = new StringBuilder();

        #region DataGrid导出专用

        /// <summary>
        /// datagrid导出数据
        /// </summary>
        /// <param name="data">datagrid的data数据的json格式</param>
        /// <param name="columns">datagrid的columns数据的json格式</param>
        /// <param name="frozencolumns">datagrid的frozencolumns数据的json格式</param>
        /// <returns></returns>
        public void ExportDataByDataGrid([ModelBinder(typeof(DataGridJsonBinder))]DataTable data, [ModelBinder(typeof(DataGridJsonBinder))]DataTable columns, [ModelBinder(typeof(DataGridJsonBinder))]DataTable frozencolumns)
        {
            //先合并冻结列和非冻结列，合并成一个DataTable
            object[] obj = new object[columns.Columns.Count];
            for (int i = 0; i < frozencolumns.Rows.Count; i++)
            {
                frozencolumns.Rows[i].ItemArray.CopyTo(obj, 0);
                columns.Rows.Add(obj);
            }

            //columns中field列的"存在于data列头"中的值 的title值
            List<string> fieldtitle_exist = new List<string>();
            //用columns中title的具体值当作列头 以title的值替换data中的列头名称
            for (int k = 0; k < columns.Rows.Count; k++)
            {
                fieldtitle_exist.Add(columns.Rows[k]["title"].ToString());
                if (data.Columns.Contains(columns.Rows[k]["field"].ToString()))
                {
                    //如果columns的field列的值存在于的data里的列头中
                    //用columns的title去替换data的列头名称
                    data.Columns[columns.Rows[k]["field"].ToString()].ColumnName = columns.Rows[k]["title"].ToString();
                }
            }
            //替换title之后，遍历data中的列头，若不存在于columns的field列的数据中，则删除data的该列
            for (int k = 0; k < data.Columns.Count; k++)
            {
                if (!fieldtitle_exist.Contains(data.Columns[k].ColumnName))
                {
                    data.Columns.RemoveAt(k);
                }
            }

            if (data.Rows.Count > 0)
            {
                string TableString = "";
                TableString += TableStart(data.Rows.Count + 1, data.Columns.Count);
                RowStart();
                // 第一行为标题行
                foreach (DataColumn dc in data.Columns)
                {
                    CellWithoutFormula("String", dc.ColumnName);
                }
                RowEnd();
                // 其它行为数据行
                foreach (DataRow row in data.Rows)
                {
                    RowStart();
                    for (int k = 0; k < data.Columns.Count; k++)
                    {
                        CellWithoutFormula("String", row[k] == null ? "" : row[k].ToString());
                    }
                    RowEnd();
                }
                TableString += content.ToString();
                TableString += TableEnd();
                string ModePath = Server.MapPath("~/Content/ExcelMode.xml");
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(ModePath);
                string ExcelXmlStr = xmlDoc.InnerXml;
                ExcelXmlStr = ExcelXmlStr.Insert(ExcelXmlStr.IndexOf("</Worksheet>"), TableString);
                GenerateByHtmlString(NewTimeStamp(), ExcelXmlStr);
            }
        }

        #endregion

        /// <summary>
        /// 用html数据导出到Excel
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="tempHtml"></param>
        private void GenerateByHtmlString(string fileName, string tempHtml)
        {
            Response.Clear();
            Response.Buffer = true;
            Response.Charset = "utf-8";
            string Filename = Server.UrlDecode(fileName) + ".xls";
            Response.AppendHeader("Content-Disposition", "attachment;filename=" + Server.UrlEncode(Filename));
            Response.ContentEncoding = System.Text.Encoding.UTF8;
            Response.ContentType = "application/ms-excel";
            //this.EnableViewState = false;
            Response.Write(tempHtml);
            Response.End();
        }

        #region 画excel

        private string TableStart(int rows, int columns)
        {
            string TableString = "";
            TableString += "<Table ss:ExpandedRowCount=\"" + rows + "\" ss:ExpandedColumnCount=\"" + columns + "\" x:FullColumns=\"1\" \n";
            TableString += "x:FullRows=\"1\" ss:DefaultColumnWidth=\"54\" ss:DefaultRowHeight=\"13.5\"> \n";
            return TableString;
        }

        private string TableEnd()
        {
            string TableString = "";
            TableString += "</Table>\n";
            return TableString;
        }

        private void RowStart()
        {
            content.Append("<Row>\n");
        }

        private void RowEnd()
        {
            content.Append("</Row>\n");
        }

        private void CellWithoutFormula(string DataType, string Data)
        {
            content.Append("<Cell><Data ss:Type=\"" + DataType + "\">" + Data + "</Data></Cell>\n");
        }

        private void CellWithFormula(string DataType, string Formula)
        {
            content.Append("<Cell ss:Formula=\"=" + Formula + "\"><Data ss:Type=\"" + DataType + "\"></Data></Cell>\n");
        }

        #endregion

        #region 其他

        /// <summary>
        /// 根据时间生成文件名
        /// </summary>
        /// <returns></returns>
        public string NewTimeStamp()
        {
            string strFileName;

            //生成文件名: 当前年月日小时分钟秒+ 随机数
            Random rd = new Random(int.Parse(DateTime.Now.ToString("MMddhhmmss")));
            strFileName = DateTime.Now.ToString("yyyyMMdd")
                + DateTime.Now.Hour
                + DateTime.Now.Minute
                + DateTime.Now.Second
                + rd.Next(999999).ToString();
            return strFileName;
        }

        #endregion

    }
}
